package atndTwitter

import org.scala_tools.time.Imports._
import scala.xml._
import scala.util.control.Exception._

object EventSearch{

  val EVENT_ID = "event_id"
  val KEYWORD = "keyword"
  val KEYWORD_OR = "keyword_or"
  val USER_ID = "user_id"
  val NICKNAME= "nickname"
  val TWITTER_ID = "twitter_id"
  val OWNER_ID = "owner_id"
  val OWNER_NICKNAME = "owner_nickname"
  val OWNER_TWITTER_ID = "owner_twitter_id"
  val START = "start"
  val COUNT = "count"
  
  private def formatParams( prefix:String , params:Seq[Any] ):String = {
    if( ! params.isEmpty )
      params.mkString( prefix + "=" , "&" + prefix + "=" , "" )
    else 
      ""
  }
  
  private def getInt( n :Node )( tag:String ):Int = ( n \ tag text ) toInt 
  
  private def getString( n :Node )( tag:String ):String = n \ tag text


  def search(
    eventId :Option[Int] = None,
    keyword :Seq[String] = Nil,
    keywordOr :Seq[String] = Nil,
    date :Seq[DateTime] = Nil,
    userId :Seq[Int] = Nil,
    nickname :Seq[String] = Nil,
    twitterId :Seq[String] = Nil,
    ownerId :Seq[Int] = Nil,
    ownerNickname :Seq[String] = Nil,
    ownerTwitterId :Seq[String] = Nil ,
    start :Option[Int] = None,
    count :Option[Int] = None
  ):SearchResult = {
  
    val params = Map(
          EVENT_ID -> eventId.toList  , 
          KEYWORD -> keyword,
          KEYWORD_OR -> keywordOr,
          USER_ID -> userId ,
          NICKNAME -> nickname ,
          TWITTER_ID -> twitterId , 
          OWNER_ID -> ownerId , 
          OWNER_NICKNAME -> ownerNickname ,
          OWNER_TWITTER_ID-> ownerTwitterId,
          START-> start.toList,
          COUNT -> count.toList 
         ).view.map{case (a,b) => formatParams( a,b ) }.filterNot{"" == }.mkString("&")
  
    val x = XML.load( new java.net.URL( "http://api.atnd.org/events?" + params ))
    
    val func = getInt(x) _

    SearchResult(
      func( "results_returned" ),
      func( "results_start" ),
      func( "results_available" ),
      ( x \\ "event" ).map{ Event.apply }.flatten
    )
    
  }

  case class SearchResult(
     resultsReturned:Int,
     resultsStart:Int,
     resultsAvailable:Int,
     events: Seq[Event]
   ){
  }

  case class User( userId: Int, nickname: String, twitterId :String )

  case class Event(
     eventId : Int,
     title : String,
     `catch` : String ,
     description : String,
     eventUrl : String,
     startedAt : Option[DateTime] ,
     endedAt : Option[DateTime] ,
     url : String,
     limit : Option[Int],
     address : String,
     place : String,
     lat : String,
     lon : String,
     owner : User,
     accepted : Int,
     waiting : Int,
     updatedAt : Option[DateTime]
  ){}
   
  object Event{
   
    def apply(node:Node):Option[Event] = {
   
      val int = getInt(node) _
      val str = getString(node) _
      def dateOpt(label:String) = allCatch opt new DateTime( getString(node)(label) )
      
      noCatch opt {
        Event(
          eventId = int("event_id"),
          title = str("title"),
          `catch` = str("catch") ,
          description = str("description") ,
          eventUrl = str("event_url") ,
          startedAt = dateOpt("started_at"),
          endedAt = dateOpt("ended_at"),
          url = str("url"),
          limit = catching(classOf[NumberFormatException]).opt(int("limit")),
          address = str("address"),
          place = str("place"),
          lat = str("lat"),
          lon = str("lon"),
          owner = User( int("owner_id") , str("owner_nickname"), str("owner_twitter_id") ),
          accepted = int("accepted"),
          waiting = int("waiting"),
          updatedAt = dateOpt("updated_at")
        )
     }
   }
  }
}